use serde::Deserialize;
use std::fs;
use std::path::PathBuf;

#[derive(Debug, Deserialize, Clone)]
pub struct Config {
    pub server: ServerConfig,
    pub security: SecurityConfig,
}

#[derive(Debug, Deserialize, Clone)]
pub struct ServerConfig {
    pub http_port: u16,
    pub interval_ms: u64,
}

#[derive(Debug, Deserialize, Clone)]
pub struct SecurityConfig {
    pub token: String,
}

impl Config {
    pub fn load() -> Result<Self, String> {
        let mut candidates: Vec<PathBuf> = Vec::new();
        if let Ok(current_dir) = std::env::current_dir() {
            candidates.push(current_dir.join("config.toml"));
        }
        if let Ok(exe_path) = std::env::current_exe() {
            if let Some(parent) = exe_path.parent() {
                candidates.push(parent.join("config.toml"));
            }
        }
        candidates.push(PathBuf::from("config.toml"));

        let config_path = candidates
            .into_iter()
            .find(|path| path.exists())
            .ok_or_else(|| {
                "config.toml not found in current or executable directory".to_string()
            })?;

        let content = fs::read_to_string(&config_path)
            .map_err(|err| format!("failed to read config ({}): {err}", config_path.display()))?;

        toml::from_str(&content)
            .map_err(|err| format!("invalid config format ({}): {err}", config_path.display()))
    }
}

pub fn validate_token(config: &Config, token: &str) -> bool {
    config.security.token.is_empty() || config.security.token == token
}
